package com.star.uc.factory.login.impl;


import com.star.common.core.context.SpringContext;
import com.star.common.core.context.ThreadContext;
import com.star.common.core.contract.constant.ContextConstants;
import com.star.common.core.operator.OperatorRouter;
import com.star.common.core.utils.BizAssert;
import com.star.common.kit.lang.StrPoolUtils;
import com.star.uc.contract.constant.UserRedisConstants;
import com.star.uc.contract.dto.request.LoginRequest;
import com.star.uc.contract.enums.*;
import com.star.uc.contract.enums.uid.GeneratorUidTypeEnum;
import com.star.uc.contract.param.UserInfoParam;
import com.star.uc.contract.param.UserOuterMapperInfoParam;
import com.star.uc.factory.login.AbstractLoginTypeOperator;
import com.star.uc.infras.repository.model.UserInfoBO;
import com.star.uc.infras.repository.model.UserOuterMapperInfoBO;
import com.star.uc.infras.utils.RedisUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
 * email邮件登录
 *
 * @author zhouhengzhe
 * @version 1.0
 * @date 2023/10/19 17:31
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class EmailLoginTypeOperator extends AbstractLoginTypeOperator {

    /**
     * 检查对应的登录类型的参数
     *
     * @param loginRequest 登录信息
     */
    @Override
    public void checkParam(LoginRequest loginRequest) {
        BizAssert.notNullWarn(loginRequest.getEmailRequest(), UserErrorEnum.EMAIL_INFO_NULL);
        BizAssert.notBlankWarn(loginRequest.getEmailRequest().getEmail(), UserErrorEnum.EMAIL_NULL);
        BizAssert.notNullWarn(loginRequest.getEmailRequest().getCode(), UserErrorEnum.EMAIL_CODE_NULL);
    }

    /**
     * 登录
     *
     * @param loginRequest 登录请求
     * @return 用户信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserInfoBO authorize(LoginRequest loginRequest) {
        //1、检验参数
        this.checkParam(loginRequest);
        LoginRequest.EmailRequest emailRequest = loginRequest.getEmailRequest();
        //2、校验验证码
        Integer code = (Integer) SpringContext.getBean(RedisUtils.class).get(UserRedisConstants.USER_EMAIL_VALIDATE_CODE +
                SendBizTypeEnum.REG.getCode() +
                StrPoolUtils.COLON +
                loginRequest.getTenantId() + StrPoolUtils.COLON +
                emailRequest.getEmail());
        BizAssert.isTrueWarn(loginRequest.getEmailRequest().getCode().equals(code), UserErrorEnum.EMAIL_CODE_ERROR);
        //3、先查询当前邮件用户是否已经存在,正常得并且时email类型的（应用ID+邮箱+类型）
        UserOuterMapperInfoBO userOuterMapperInfoBO = UserOuterMapperInfoParam
                .builder()
                .tenantId(loginRequest.getTenantId())
                .identifier(emailRequest.getEmail())
                .loginType(loginRequest.getLoginType())
                .build().one();
        //4、用户不存在创建新账号
        UserInfoBO userInfoBO;
        if (Objects.isNull(userOuterMapperInfoBO)) {
            userInfoBO = this.createUser(loginRequest, null);
            //事务问题，需要先保存用户信息，然后再创建用户映射
            SpringContext.getBean(EmailLoginTypeOperator.class).createUserMapping(userInfoBO.getUid(), loginRequest, null);
            //设置当前IP数递增
            //  user:email:tenantId:ip:count:tenantId(前端给):email:ip(后端自己拿)
            SpringContext.getBean(RedisUtils.class).incr(UserRedisConstants.USER_TENANT_ID_IP_COUNT +
                    loginRequest.getTenantId() + StrPoolUtils.COLON + LimitTypeEnum.EMAIL.getCode() + StrPoolUtils.COLON +
                    ThreadContext.get(ContextConstants.IP), 1);
        } else {
            userInfoBO = UserInfoParam.builder().uid(userOuterMapperInfoBO.getUid()).build().one();
        }
        //判断当前用户是否不存在或者被禁用
        return checkUserInfoExistOrDisable(userInfoBO, loginRequest);
    }

    /**
     * Operator的名称, 同一类型的Operator的路由器{@link OperatorRouter}能够根据该值路由到当前的Operator
     *
     * @return route key
     */
    @Override
    public String getName() {
        return LoginTypeEnum.EMAIL.getCode();
    }


    /**
     * 创建用户
     *
     * @param loginRequest 登录请求信息
     * @param authUser     第三方登录信息
     * @return 用户信息
     */
    @Override
    public UserInfoBO createUser(LoginRequest loginRequest, AuthUser authUser) {
        //创建用户
        UserInfoBO userInfoBO = UserInfoBO
                .builder()
                .uid(GeneratorUidTypeEnum.getUidByType())
                .nickName(loginRequest.getEmailRequest().getEmail())
                .tenantId(loginRequest.getTenantId())
                .areaCode(ThreadContext.get(ContextConstants.AREA_CODE))
                .status(UserStatusEnum.NORMAL.getCode())
                .build();
        userInfoBO.save();
        return userInfoBO;
    }

    /**
     * 创建用户映射
     *
     * @param uid          用户ID
     * @param loginRequest 登录请求信息
     */
    @Override
    public void createUserMapping(String uid, LoginRequest loginRequest, AuthUser authUser) {
        LoginRequest.EmailRequest emailRequest = loginRequest.getEmailRequest();
        UserOuterMapperInfoBO
                .builder()
                .uid(uid)
                .loginType(loginRequest.getLoginType())
                .tenantId(loginRequest.getTenantId())
                .identifier(emailRequest.getEmail())
                .build().save();
    }
}
